﻿#ifndef XFFMPEG_H
#define XFFMPEG_H

#pragma once
#include <iostream>
#include <QMutex>

extern "C"{//必须
#include "libavformat/avformat.h"       //封装格式处理
#include "libswscale/swscale.h"         //视频像素数据格式转换
#include "libswresample/swresample.h"   //音频采样数据格式转换
}


class XFFMpeg
{
public:
    ~XFFMpeg();
    static XFFMpeg *init(){
        static XFFMpeg ff;
        return &ff;
    }

    int getDuration(){return _totalMs;}
    int getVideoStreamIndex(){return _videoStream;}
    int getAudioStreamIndex(){return _audioStream;}
    double getFPS(){return _fps;}
    AVFrame* getVideoFrame(){return _yuv;}
    AVFrame* getAudioFrame(){return _pcm;}

    int _sampleRate = 0;
    int _sampleSize = 16;
    int _channel = 0;
    AVSampleFormat _sampleFormat;

    /**
     * @brief Open打开文件
     * @param path
     * @return
     */
    bool open(const char *path);
    /**
     * @brief close
     */
    void close();
    /**
     * @brief getError
     * @return
     */
    std::string getError();

    /**
     * @brief read one frame
     * @return
     */
    AVPacket read();

    /**
     * @brief decode the frame to yuv
     * @param pkt
     * @return
     */
    int decode(const AVPacket* pkt);

    /**
     * @brief toRGB yuv->RGB
     * @param yuv
     * @param out 输出到image
     * @param outwidth 显示宽
     * @param outheight 显示高
     * @return
     */
    bool toRGB(const AVFrame* yuv, char* out, int outwidth, int outheight);

    int toPCM(char* out);

private:
    QMutex _mutex;

    AVFormatContext* _ic {Q_NULLPTR};
    AVFrame* _yuv {Q_NULLPTR};
    AVFrame* _pcm {Q_NULLPTR};
    SwsContext* _cCtx {Q_NULLPTR};//转码器上下文
    SwrContext* _aCtx {Q_NULLPTR};

    int _totalMs = 0;
    int _videoStream = -1;
    int _audioStream = -1;
    int _pts = 0;

    double _fps = 0;

    char _errBuf[1024];

private:
    XFFMpeg();
};

#endif // XFFMPEG_H
